LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;


entity mycpu is
port ( 

  CLK							:		in	std_logic;  -- clock signal
  nReset					:		in	std_logic;  -- reset for processor
  halt						:		out	std_logic;  -- halt for processor
  
  baseAddr      : in std_logic_vector(31 downto 0);
  
  dcMemRead        : out  std_logic;                       -- CPU side
  dcMemWrite       : out  std_logic;                       -- CPU side
  dMemWait        : in std_logic;                       -- CPU side
  dMemAddr        : out  std_logic_vector (15 downto 0);  -- CPU side
  dMemDataRead    : in std_logic_vector (31 downto 0);  -- CPU side
  dMemDataWrite   : out  std_logic_vector (31 downto 0);  -- CPU side
  
  iMemRead        : out  std_logic;                       -- CPU side
  iMemWait        : in std_logic;                       -- CPU side
  iMemAddr        : out  std_logic_vector (15 downto 0);  -- CPU side
  iMemData        : in std_logic_vector (31 downto 0);  -- CPU side
  
  ext_Link            : out std_logic
);



end mycpu;

architecture struct of mycpu is


component alu is
    port (opcode: IN STD_LOGIC_VECTOR (3 downto 0); A, B: IN STD_LOGIC_VECTOR (31 downto 0); output: OUT STD_LOGIC_VECTOR (31 downto 0); negative: OUT STD_LOGIC; overflow, zero: OUT STD_LOGIC);
end component;
 
component registerFile is
           port
           (wdat		  :	in	std_logic_vector (31 downto 0); wsel		  :	in	std_logic_vector (4 downto 0); 
           wen		   :	in	std_logic; clk		   :	in	std_logic; nReset	 :	in	std_logic; 
           rsel1		 :	in	std_logic_vector (4 downto 0); rsel2		 :	in	std_logic_vector (4 downto 0); 
           rdat1		 :	out	std_logic_vector (31 downto 0); rdat2		 :	out	std_logic_vector (31 downto 0));
end component;

component control is
  port ( 
    op          : IN STD_LOGIC_VECTOR (5 downto 0); --Upper 6 bits of MIPS instruction
    funct       : IN std_logic_vector (5 downto 0); --Lower 6 bits
    RegDst      : OUT STD_LOGIC;    --mux control
    Jump        : OUT STD_LOGIC;
    Branch      : OUT STD_LOGIC;    
    BranchNE    : OUT STD_LOGIC;
    MemRead     : OUT STD_LOGIC;   --ramd read enable
    MemtoReg    : OUT STD_LOGIC;  --mux control
    ALUOp       : OUT STD_LOGIC_VECTOR (3 downto 0);
    MemWrite    : OUT STD_LOGIC;  --ramd write enable
    ALUSrc      : OUT STD_LOGIC;    --mux control
    RegWrite    : OUT STD_LOGIC; --register write enable
    ExtOp       : OUT STD_LOGIC;
    Shift       : OUT STD_lOGIC;
    LoadUpper   : OUT STD_lOGIC;
    JumpReg     : OUT STD_LOGIC;
    Link        : OUT STD_LOGIC
  );
end component;

component programcounter is
  port (CLK	:	in	std_logic; nReset : in std_logic; baseAddr : in std_logic_vector(31 downto 0); PCEN : in std_logic; next_in : in std_logic_vector (31 downto 0); curr_out : out std_logic_vector (31 downto 0));
end component;
  
component addr
  port (A, B: in std_logic_vector(31 downto 0); CARRYIN : in std_logic; SUM : out std_logic_vector(31 downto 0); OVERFLOW: out std_logic);
end component;

component extendunit is
  port ( 
    Imm         :   in std_logic_vector (15 downto 0);
    ExtOp         : in std_logic;
    Shift         : in std_logic;
    LoadUpper     : in std_logic;
    ImmExtend    :   out std_logic_vector (31 downto 0)
  );
end component;

component regfetch is
  port ( 
    CLK							     :		 in	std_logic;
    nReset         :   in std_logic;
    ifen           :   in std_logic;
    fInstruction   :   in std_logic_vector(31 downto 0);
    fPC4           :   in std_logic_vector(31 downto 0);
    dInstruction   :  out std_logic_vector(31 downto 0);
    dPC4           :  out std_logic_vector(31 downto 0)
  );
end component;

component regdecode is
  port ( 
    CLK							     :		 in	std_logic;
    nReset         :   in std_logic;
    iden           :   in std_logic;
    dPC4           :   in std_logic_vector (31 downto 0);     --in from fetch
    dREG_RDAT1     :   in std_logic_vector (31 downto 0);     --in from fetch PC+4 addr
    dREG_RDAT2     :   in std_logic_vector (31 downto 0);     --in from fetch PC+4 addr
    dRt            :   in std_logic_vector (4 downto 0); --instruction(20 downto 16)
    dRd            :   in std_logic_vector (4 downto 0); --instruction(15 downto 11)
    dRs            :   in std_logic_vector (4 downto 0);
    dImmExtend        :   in std_logic_vector (31 downto 0);
    dWBctrl        :   in std_logic_vector (3 downto 0);
    dMEMctrl       :   in std_logic_vector (2 downto 0);
    dEXctrl        :   in std_logic_vector (6 downto 0);
    dhalt          :   in std_logic;

    exPC4          :   out std_logic_vector (31 downto 0);    --out to decode
    exREG_RDAT1    :   out std_logic_vector (31 downto 0);     --out to decode
    exREG_RDAT2    :   out std_logic_vector (31 downto 0);     --out to decode
    exRt           :   out std_logic_vector (4 downto 0); --instruction(20 downto 16)
    exRd           :   out std_logic_vector (4 downto 0); --instruction(15 downto 11)
    exRs           :   out std_logic_vector (4 downto 0);
    exImmExtend       :   out std_logic_vector (31 downto 0);
    exWBctrl       :   out std_logic_vector (3 downto 0);
    exMEMctrl      :   out std_logic_vector (2 downto 0);
    EXctrl         :   out std_logic_vector (6 downto 0);
    exhalt         :   out std_logic
  );
end component;

component regex is
  port ( 
    CLK							     :		 in	std_logic;
    nReset         :   in std_logic;
    bubble         :   in std_logic;
    exen           :   in std_logic;
    exPC4          :   in std_logic_vector (31 downto 0);   
    exALU_out      :   in std_logic_vector(31 downto 0);
    exREG_RDAT2    :   in std_logic_vector(31 downto 0);
    exRd           :   in std_logic_vector(4 downto 0);
    exWBctrl       :   in std_logic_vector(3 downto 0);
    exMEMctrl      :   in std_logic_vector(2 downto 0);
    exImmExtend    :   in std_logic_vector(31 downto 0);
    exhalt         :   in std_logic;
    
    memALU_out     :   out std_logic_vector(31 downto 0);
    memREG_RDAT2   :   out std_logic_vector(31 downto 0);
    memRd    :   out std_logic_vector(4 downto 0);
    memWBctrl      :   out std_logic_vector(3 downto 0);
    MEMctrl        :   out std_logic_vector(2 downto 0);
    memImmExtend   :   out std_logic_vector(31 downto 0);
    memhalt        :   out std_logic;
    memPC4          :   out std_logic_vector (31 downto 0)    
  );
end component;

component regmem is
  port ( 
    CLK							     :		 in	std_logic;
    nReset         :   in std_logic;
    memen           :   in std_logic;
    memPC4          :   in std_logic_vector (31 downto 0);    
    memDMEM_out     :  in std_logic_vector(31 downto 0);
    memALU_out      :  in std_logic_vector(31 downto 0);
    memRd     :  in std_logic_vector(4 downto 0);
    memWBctrl       :  in std_logic_vector(3 downto 0);
    memImmExtend    :  in std_logic_vector(31 downto 0);
    memhalt         :  in std_logic;
    
    wbDMEM_out     :  out std_logic_vector(31 downto 0);
    wbALU_out      :  out std_logic_vector(31 downto 0);
    wbRd     :  out std_logic_vector(4 downto 0);
    WBctrl         :  out std_logic_vector(3 downto 0);
    wbImmExtend    :  out std_logic_vector(31 downto 0);
    wbhalt         :  out std_logic;
    wbPC4          :   out std_logic_vector (31 downto 0)
  );
end component;

component hazard is
  port (
    exMemRead   : in std_logic;
    
    exRt, dRs, dRt  : in std_logic_vector(4 downto 0);
    
    pcen, ifen, Hazard      : out std_logic

  );
end component;

component forwarder is
  port (
    exRs, exRt, memRd, wbRd :     in std_logic_vector(4 downto 0);
    memRegWrite, wbRegWrite :     in std_logic;
    forwardA, forwardB      :     out std_logic_vector(1 downto 0)

  );
end component;

component branchcontrol is
  port (
    dRs, dRt, exRd, memRd :     in std_logic_vector(4 downto 0);
    exRegWrite, memRegWrite :     in std_logic;
    dImmExtend, dPC4          :   in std_logic_vector(31 downto 0);
    Branch, BranchNE, JumpReg          :   in std_logic;
    REG_RDAT1, REG_RDAT2      :   in std_logic_vector(31 downto 0);
    exALU_out, memALU_out     :   in std_logic_vector(31 downto 0);
    
    BranchTaken               :   out std_logic;
    Branch_Addr               :   out std_logic_vector(31 downto 0)
  );
end component;



------------------------    SIGNALS ----------------------------

  subtype word is std_logic_vector(31 downto 0);
  subtype address is std_logic_vector(15 downto 0);
  subtype REG_SPEC is std_logic_vector(4 downto 0);
  
-- Program Counter Signals
  signal PCEN : std_logic;
  signal PC_next, PC_addr, PC4, memPC4, wbPC4, Branch_addr, Branch_B, Jump_addr, PC_SRC_MUX1, PC_SRC_MUX2 : WORD;
  signal BraComp, BranchTaken : std_logic;
  
-- Instruction Signals
  signal Instruction, fInstruction : WORD;
  signal opcode : std_logic_vector(5 downto 0);
  signal rs, rt, rd : REG_SPEC;
  signal funct : std_logic_vector(5 downto 0);
  signal shamt : std_logic_vector(4 downto 0);
  signal imm  : std_logic_vector (15 downto 0);
  signal ImmUpper, ImmExtend, dImmExtend, exImmExtend, memImmExtend : WORD;
  
-- Register File Signals
  signal REG_WDAT, REG_WDAT_MUX1, REG_WDAT_MUX2, REG_RDAT1, exREG_RDAT1, REG_RDAT2, exREG_RDAT2, memREG_RDAT2 : WORD;
  signal REG_WEN : std_logic;
  signal REG_WSEL, REG_WSEL_MUX1, exRdnew, memRd, wbRd : REG_SPEC;
  
-- Control Signals
  signal RegDst, Jump, Branch, BranchNE, MemRead, MemtoReg, MemWrite, ALUSrc, RegWrite, ExtOp, Shift, LoadUpper, JumpReg : std_logic;
  signal dRegDst, dJump, dMemtoReg, dMemRead, dMemWrite, dALUSrc, dRegWrite, dShift, dLoadUpper : std_logic;
-- ALU Signals
  signal ALU_A, ALU_B, ALU_B_mux1, ALU_out, exALU_out, memALU_out, memBranch, wbALU_out : word;
  signal ALU_n, ALU_v, ALU_z  : std_logic;
  signal ALUOp, dALUOp : std_logic_vector(3 downto 0);
  
-- Data Memory Signals
  signal DMEM_addr : WORD;
  signal DMEM_in, DMEM_out, memDMEM_out, wbDMEM_out : WORD;
  signal DMEM_we, ramready : std_logic;
    
-- DECODE SIGNALS  
  signal dPC4, exPC4, dREG_RDAT1, dREG_RDAT2 : WORD;
  signal exRt, exRd, exRs, dRt, dRd : REG_SPEC;
  signal dWBctrl, exWBctrl, memWBctrl, WBctrl : std_logic_vector(3 downto 0);
  signal dMEMctrl, exMEMctrl, MEMctrl : std_logic_vector(2 downto 0);
  signal  dEXctrl, EXctrl : std_logic_vector(6 downto 0);
  signal Link, dLink : std_logic;
  
--ENABLE SIGNALS

  signal ifen, iden, exen,exbubble,  memen : std_logic;
  
  signal dhalt, exhalt, memhalt, wbhalt : std_logic;
  
  signal hazard_select, haz_exMemRead, hazpcen, hazifen : std_logic;
  
  signal forwardA, forwardB : std_logic_vector(1 downto 0);
  
  
begin   

    
    --*********************************************************************-- 
    ----------------------FETCH STAGE---------------------------------------
    --*********************************************************************--

--PROGRAM COUNTER and SOURCE SELECTIONS  
PC_ADD4 : addr PORT MAP (A => PC_addr, B => x"00000004", carryin => '0', sum => PC4);
  
  
  PCENABLE : process (iMemWait, dMemWait, dhalt, hazpcen, BranchTaken, Jump, JumpReg, wbhalt)
  
  begin
    
    if (dhalt = '1' or hazpcen = '0' or wbhalt = '1') then
      PCEN <= '0';
    elsif ((BranchTaken = '1' or Jump = '1' or JumpReg = '1') and dMemWait = '0') then 
      PCEN <= '1';
    elsif (iMemWait = '1' or dMemWait = '1') then
      PCEN <= '0';
    else
      PCEN <= '1';
    end if;
    
  end process PCENABLE;
  
  --PCEN <= '1' when (BranchTaken or Jump or JumpReg) or (not iMemWait and not dMemWait and not dhalt and hazpcen) else
     --     '0' when iMemWait

-- PC_SRC_MUX1
  PC_SRC_MUX1 <= Branch_addr when BranchTaken = '1' or JumpReg = '1' else
               PC4;

-- PC_SRC_MUX2
  PC_next <= Jump_addr when Jump = '1' else
           PC_SRC_MUX1;
           
         
  
  PC : programcounter
    PORT MAP (
      CLK         => CLK,
      nReset      => nReset,
      PCEN        => PCEN,
      baseAddr    => baseAddr,
      next_in     => PC_next, --result of two mux decisions and math
      curr_out    => PC_addr --goes to I_Memory read address
    );




--On any jump instruction (JAL, JR, and J) the incoming instruction must be ignored because
----the PC is being modified to the correct instruction, necessitating a no op.


--IF.FLUSH                          |*********| this fixed it :-)
with (Jump or JumpReg or BranchTaken or iMemWait) select
   fInstruction <= x"00000000" when '1',  --insert nop into the IF/ID register
                   iMemData when others;     --Normal function

  ifen <= hazifen and not dMemWait and not dhalt;-- and (MemRead nor MemWrite); --and (MemWrite nor MemRead);
  IFREG : regfetch 
    PORT MAP ( 
      CLK							     => CLK,
      nReset         => nReset,
      ifen           => ifen,
      fInstruction   => fInstruction,
      fPC4           => PC4,
      dInstruction   => Instruction,
      dPC4           => dPC4
    );

    
  dhalt <= '1' when Instruction = x"FFFFFFFF" else
            '0';
--*********************************************************************-- 
----------------------DECODE STAGE---------------------------------------
--*********************************************************************--
  opcode <= Instruction(31 downto 26);
  rs <= Instruction(25 downto 21);
  rt <= Instruction(20 downto 16);
  rd <= Instruction(15 downto 11);
  shamt <= Instruction(10 downto 6);
  funct <= Instruction(5 downto 0);
  imm <= Instruction(15 downto 0);

  
--REGISTERFILE AND SOURCE SELECTIONS
                
    REG : registerFile 
      PORT MAP (
        wdat      => REG_WDAT, --input from mux select between D_RAM output and ALU result
        wsel      => REG_WSEL, --mux input, select on RegDst from control between Instruction [20-16] and Instruction [15-11] 
        wen       => REG_WEN, --RegWrite from control
        clk       => CLK, --
        nReset    => nReset, 
        rsel1     => rs, --Instruction [25-21]
        rsel2     => rt, --Instruction [20-16]
        rdat1     => REG_RDAT1, 
        rdat2     => REG_RDAT2  --into a mux
      );

haz_exMemRead <= exMemctrl(0) or exMEMctrl(2);
  HAZ : hazard 
    port map(
    exMemRead   => haz_exMemRead,    
    exRt        => exRdnew, 
    dRs         => Rs, 
    dRt         => dRt,    
    pcen        => hazpcen, 
    ifen        => hazifen, 
    Hazard      => hazard_select);
-- extend unit achieves both sign or zero extension based on ExtOp
-- on a shift it provides shamt to ALU_b
  U00 : extendunit
    PORT MAP (Imm => imm, ExtOp => ExtOp, Shift => dShift, LoadUpper => dLoadUpper, ImmExtend => dImmExtend);

  Jump_addr <= dPC4(31 downto 28) & Instruction(25 downto 0) & "00";

  BraCon : branchcontrol 
  port map(
    dRs          =>  Rs, 
    dRt          =>  dRt, 
    exRd         =>  exRdnew,
    memRd        =>  memRd,
    exRegWrite   =>  exWBctrl(1), 
    memRegWrite  =>  memWBctrl(1),
    dImmExtend   =>  dImmExtend, 
    dPC4         =>  dPC4,
    Branch       =>  Branch, 
    BranchNE     =>  BranchNE,
    REG_RDAT1    =>  dREG_RDAT1, 
    REG_RDAT2    =>  REG_RDAT2,
    exALU_out    =>  exALU_out, 
    memALU_out   =>  memBranch,
    JumpReg      =>  JumpReg,     --lets reuse what we already have
    
    BranchTaken  =>  BranchTaken,
    Branch_Addr  =>  Branch_addr  ); --this will get taken on JR or BRANCH via internal trickery
      
  CON : control
    PORT MAP(
      op        => opcode, 
      funct     => funct, 
      RegDst    => dRegDst, --REG mux sel for write register
      Jump      => Jump,   --PC source mux 2
      Branch    => Branch, --PC source mux 1
      BranchNE  => BranchNE,
      MemRead   => dMemRead, --D_Memory
      MemtoReg  => dMemtoReg, --reg write data mux
      ALUOp     => dALUOp,    --ALU_0
      MemWrite  => dMemWrite, --D_Memory
      ALUSrc    => dALUSrc,   --ALU_B mux
      RegWrite  => dRegWrite,  --REG
      ExtOp     => ExtOp,
      Shift     => dShift,
      LoadUpper => dLoadUpper,
      JumpReg   => JumpReg,
      Link      => dLink
    );

--JAL Logic
----dRt gets 31 to control where its stored
----dRd gets 0 to prevent any invalid writes
----the RDAT1 gets the current dPC4 to allow the value to propogate through piples and eventually be written back correctly
with (Jump and dRegWrite) select
  dRt <= Rt when '0',
         "11111" when '1',
         "00000" when others;

with (Jump and dRegWrite) select
  dRd <= Rd when '0',
         "00000" when '1',
         "00000" when others;
with (Jump and dRegWrite) select
  dREG_RDAT1 <= REG_RDAT1 when '0',
                x"0000" & dPC4(15 downto 0) when '1',
                x"BDBDBDB3" when others;

  dWBctrl  <= Jump & dMemtoReg & dRegWrite & dLoadUpper when hazard_select = '0' else
              (others => '0'); --3
  dMEMctrl <= dLink & dMemWrite & dMemRead when hazard_select = '0' else
              (others => '0');  --2
  dEXctrl  <= dALUSrc & dALUOp & dRegDst & dShift when hazard_select = '0' else
              (others => '0'); --7

  iden <= not dMemWait and not exhalt;
  DREG : regdecode
    PORT MAP ( 
      CLK							     => CLK,
      nReset         => nReset,
      iden           => iden,
      dPC4           => dPC4,
      dREG_RDAT1     => dREG_RDAT1,
      dREG_RDAT2     => REG_RDAT2,
      dRt            => dRt,
      dRd            => dRd,
      dRs            => Rs,
      dImmExtend     => dImmExtend,
      dWBctrl        => dWBctrl,
      dMEMctrl       => dMEMctrl,
      dEXctrl        => dEXctrl,
      dhalt          => dhalt,
  
      exPC4          => exPC4,
      exREG_RDAT1    => exREG_RDAT1,
      exREG_RDAT2    => exREG_RDAT2,
      exRt           => exRt,
      exRd           => exRd,
      exRs           => exRs,
      exImmExtend    => exImmExtend,
      exWBctrl       => exWBctrl,
      exMEMctrl      => exMemctrl,
      EXctrl         => EXctrl,
      exhalt         => exhalt
    );

--*********************************************************************-- 
----------------------EXECUTE STAGE---------------------------------------
--*********************************************************************--
ALUSrc <= EXctrl(6);
ALUOp  <= EXctrl(5 downto 2);
RegDst <= EXctrl(1);
Shift  <= EXctrl(0);

  exRdnew  <=  exRd when RegDst = '1' else
               exRt;

--Alu_A
  with forwardA select
    ALU_A <= exREG_RDAT1  when  "00",
             memALU_out   when  "10",
             REG_WDAT     when  "01",
             x"BADABADA"  when  others;
  
 -- ALU_A <= exREG_RDAT1;
           
  with forwardB select
    ALU_B_mux1 <=  exREG_RDAT2  when  "00",
                   memALU_out   when  "10",
                   REG_WDAT     when  "01",
                   x"BADBBADB"  when  others;
--ALU_SRC_MUX1
  ALU_B <= exImmExtend when ALUSrc = '1' else
           ALU_B_mux1;
           
    ALU_0 : alu
      PORT MAP (
        opcode      => ALUOp,      --from control
        A           => ALU_A, 
        B           => ALU_B,           --input is muxed
        output      => ALU_out, --goes to D_mem address and register data input mux
        negative    => ALU_n, 
        overflow    => ALU_v,
        zero        => ALU_z
      );
      
  exALU_out <=  exImmExtend when exWBctrl(0) = '1' else
              ALU_out;

exen <= not dMemWait and not memhalt;

exbubble <= iMemWait and not dMemWait and (MemRead or MemWrite);

EXREG : regex 
  port map( 
    CLK							     => CLK,
    nReset         => nReset,
    bubble         => '0',
    exen           => exen,
    
    exALU_out      => exALU_out,
    exREG_RDAT2    => ALU_B_MUX1,
    exRd     	   => exRdnew,
    exWBctrl       => exWBctrl,
    exMEMctrl      => exMEMctrl,
    exImmExtend    => exImmExtend,
    exhalt         => exhalt,
    exPC4          => exPC4,
    
    memALU_out     => memALU_out,
    memREG_RDAT2   => memREG_RDAT2,
    memRd    	   => memRd,
    memWBctrl      => memWBctrl,
    MEMctrl        => MEMctrl,
    memImmExtend   => memImmExtend,
    memhalt        => memhalt,
    memPC4         => memPC4
  );
  
  Forward : forwarder 
    port map(
      exRs          =>  exRs, 
      exRt          =>  exRt, 
      memRd         =>  memRd, 
      wbRd          =>  wbRd,
      memRegWrite   =>  memWBctrl(1),
      wbRegWrite    =>  RegWrite,
      forwardA      =>  forwardA, 
      forwardB      =>  forwardB);

--*********************************************************************-- 
----------------------MEM STAGE---------------------------------------
--*********************************************************************--
--dMEMctrl <= dMemWrite & dMemRead;  --2
  MemWrite <= MEMctrl(1);
  MemRead  <= MEMctrl(0);
  Link     <= MEMctrl(2);
  
  
  memBranch <= dMemDataRead when Link = '1' or MemRead = '1' else memALU_out;
  
  
  dcMemRead      <= MemRead;
  dcMemWrite     <= MemWrite;
  dMemAddr      <= memALU_out(15 downto 0);
  dMemDataWrite <= memREG_RDAT2;

  iMemRead <= not wbhalt;
  iMemAddr <= PC_addr(15 downto 0);

            
  
memen <= not dMemWait and not wbhalt;

  MEMREG : regmem 
    port map( 
      CLK	     => CLK,
      nReset         => nReset,
      memen          => memen,
      
      memDMEM_out     => dMemDataRead,
      memALU_out      => memALU_out,
      memRd     	=> memRd,
      memWBctrl       => memWBctrl,
      memImmExtend    => memImmExtend,
      memhalt         => memhalt,
      memPC4          => memPC4,
      
      
      wbDMEM_out     => wbDMEM_out,
      wbALU_out      => wbALU_out,
      wbRd     		=> wbRd,
      WBctrl         => WBctrl,
      wbImmExtend    => ImmExtend,
      wbhalt         => wbhalt,
      wbPC4          => wbPC4
    );

  --*********************************************************************-- 
  ----------------------WB STAGE---------------------------------------
  --*********************************************************************--
  
--  dWBctrl  <= JAL & dMemtoReg & dRegWrite & dLoadUpper; --3
  
  MemtoReg <= WBctrl(2);
  RegWrite <= WBctrl(1);
  LoadUpper <= WBctrl(0);
  
  
  
  REG_WEN   <=  RegWrite;

                
  REG_WSEL    <= "11111" when WBctrl(3) = '1' else
                 wbRd;


  REG_WDAT_MUX1  <= wbDMEM_out when MemtoReg = '1' else
            wbALU_out;
              
  REG_WDAT_MUX2 <= ImmExtend when LoadUpper = '1' else
                   REG_WDAT_MUX1;
                   
  REG_WDAT  <= x"0000" & wbPC4(15 downto 0) when WBctrl(3) = '1' else
               REG_WDAT_MUX2;
               
  halt <= wbhalt;

  ext_link <= Link;

end struct;
